package com.billard.service.impl;


import com.billard.dto.TableStatusDTO;
import com.billard.entity.Order;
import com.billard.entity.Table;
import com.billard.exception.AccountNotFoundException;
import com.billard.mapper.OrderMapper;
import com.billard.mapper.TableMapper;
import com.billard.service.TableService;
import com.billard.utils.TableDescUtils;
import com.billard.utils.UserIdUtil;
import com.billard.vo.TableVO;
import com.billard.websocket.TableStatusPublisher;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.billard.utils.TimeUtils;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.List;
/**
 * 球台服务实现类
 */
@Service
public class TableServiceImpl implements TableService {

    @Autowired
    private TableMapper tableMapper;

    @Autowired
    private TimeUtils timeUtils;

    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private TableStatusPublisher tableStatusPublisher;

    @Autowired
    private TableDescUtils tableDescUtils;

    @Override
    public List<TableVO> getAllTables() {
        List<Table> tables = tableMapper.selectAll();
        List<TableVO> tableVOS = tables.stream().map(table -> {
            TableVO tableVO = new TableVO();
            BeanUtils.copyProperties(table, tableVO);
            return tableVO;
        }).toList();
        LocalDateTime now = LocalDateTime.now();
        for (TableVO table : tableVOS) {
            // 设置状态描述
            table.setStatusDesc(tableDescUtils.getStatusDesc(table.getStatus()));

            //  设置类型描述（使用新方法）
            table.setTypeDesc(tableDescUtils.getTypeDesc(table.getTableType()));

            // 计算当前使用时长（向上取整）
            if (table.getStartTime() != null && table.getStatus() != null && table.getStatus() == 1) {
                Duration duration = Duration.between(table.getStartTime(), now);
                long seconds = duration.getSeconds();
                int minutes = (int) ((seconds + 59) / 60); // 向上取整到分钟
                table.setCurrentDuration(minutes);
            }
        }
        return tableVOS;
    }

    @Override
    public List<Table> getTablesByStatus(Integer status) {

        return tableMapper.selectByStatus(status);
    }

    @Override
    public Table getTableById(Long id) {
        return tableMapper.selectById(id);
    }

    @Override
    public void createTable(Table table) {
        // 获取当前操作员ID
        Long currentUserId = UserIdUtil.getUserId();
        if (currentUserId != null) {
            // 可以记录操作日志
            System.out.println("创建球台操作员ID: " + currentUserId);
        }

        tableMapper.insert(table);
    }

    @Override
    public void updateTable(Table table) {
        // 获取当前操作员ID
        Long currentUserId = UserIdUtil.getUserId();
        if (currentUserId != null) {
            // 可以记录操作日志
            System.out.println("更新球台操作员ID: " + currentUserId);
        }

        tableMapper.update(table);
    }

    @Override
    public void deleteTable(Long id) {
        // 获取当前操作员ID
        Long currentUserId = UserIdUtil.getUserId();
        if (currentUserId != null) {
            // 可以记录操作日志
            System.out.println("删除球台操作员ID: " + currentUserId);
        }

        tableMapper.deleteById(id);
    }

    @Override
    @Transactional
    public void changeTableStatus(TableStatusDTO tableStatusDTO) {
        Table table = tableMapper.selectById(tableStatusDTO.getTableId());
        if (table == null) {
            throw new AccountNotFoundException("球台不存在");
        }

        // 获取当前操作员ID
        Long currentUserId = UserIdUtil.getUserId();
        if (currentUserId != null) {
            // 可以记录操作日志
            System.out.println("变更球台状态操作员ID: " + currentUserId);
        }

        // 根据目标状态执行相应操作
        switch (tableStatusDTO.getTargetStatus()) {
            case 0: // 空闲
                setTableFree(table.getId());
                break;
            case 1: // 使用中
                startUsingTable(table.getId(), tableStatusDTO.getCustomerName(), tableStatusDTO.getCustomerPhone());
                break;
            case 2: // 预约
                setTableReserved(table.getId(), tableStatusDTO.getStartTime(), tableStatusDTO.getEndTime());
                break;
            case 3: // 维护中
                setTableMaintenance(table.getId());
                break;
            default:
                throw new AccountNotFoundException("无效的状态值");
        }

        // 发布WebSocket消息
        tableStatusPublisher.publishTableStatusChange(table.getId());
    }

    @Override
    @Transactional
    public void startUsingTable(Long tableId, String customerName, String customerPhone) {
        Table table = tableMapper.selectById(tableId);
        if (table == null) {
            throw new AccountNotFoundException("球台不存在");
        }

        if (table.getStatus() != 0) {
            throw new AccountNotFoundException("球台当前不可使用");
        }

        // 获取当前操作员ID
        Long currentUserId = UserIdUtil.getUserId();
        if (currentUserId != null) {
            // 可以记录操作日志
            System.out.println("开始使用球台操作员ID: " + currentUserId);
        }

        // 更新球台状态
        table.setStatus(1);// 使用中
        table.setStartTime(LocalDateTime.now());
        table.setCurrentFee(BigDecimal.ZERO);
        tableMapper.update(table);

        // 创建订单
        Order order = new Order();
        order.setTableId(tableId);
        order.setCustomerName(customerName);
        order.setCustomerPhone(customerPhone);
        order.setStartTime(LocalDateTime.now());
        order.setHourlyPrice(table.getHourlyPrice());
        order.setStatus(0); // 进行中
        order.setOrderNumber(generateOrderNumber());
        order.setOperatorId(currentUserId);
        orderMapper.insert(order);
    }



    @Override
    @Transactional
    public void endUsingTable(Long tableId) {
        Table table = tableMapper.selectById(tableId);
        if (table == null) {
            throw new AccountNotFoundException("球台不存在");
        }

        if (table.getStatus() != 1) {
            throw new AccountNotFoundException("球台当前未在使用中");
        }

        // 获取当前操作员ID
        Long currentUserId = UserIdUtil.getUserId();
        if (currentUserId != null) {
            // 可以记录操作日志
            System.out.println("结束使用球台操作员ID: " + currentUserId);
        }

        // 计算费用
        LocalDateTime endTime = LocalDateTime.now();
        try {
            long minutes = timeUtils.calculateMinutesBetween(table.getStartTime(), endTime);
            BigDecimal totalFee = table.getHourlyPrice()
                    .multiply(BigDecimal.valueOf(minutes))
                    .divide(BigDecimal.valueOf(60), 2, RoundingMode.HALF_UP);

            // 更新球台状态
            table.setStatus(0);
            table.setEndTime(endTime);
            table.setCurrentFee(BigDecimal.ZERO);
            tableMapper.update(table);

            // 更新订单
            Order order = orderMapper.selectActiveByTableId(tableId);
            if (order != null) {
                order.setEndTime(endTime);
                order.setDuration((int) minutes);
                order.setTotalFee(totalFee);
                order.setStatus(1); // 已结算
                orderMapper.update(order);
            }
        } catch (IllegalArgumentException e) {
            // 记录异常信息并抛出自定义异常
            System.err.println("计算球台使用费用失败: " + e.getMessage());
            throw new RuntimeException("球台使用时间信息不完整，无法计算费用");
        }
    }

    @Override
    public void pauseTable(Long tableId) {
        // 获取当前操作员ID
        Long currentUserId = UserIdUtil.getUserId();
        if (currentUserId != null) {
            // 可以记录操作日志
            System.out.println("暂停球台操作员ID: " + currentUserId);
        }

        // 暂停逻辑：记录暂停时间，但不结束订单
        Table table = tableMapper.selectById(tableId);
        if (table != null && table.getStatus() == 1) {
            // 更新球台状态为暂停（这里我们使用状态3表示暂停）
            table.setStatus(4); // 4表示暂停
            tableMapper.update(table);

            // 更新订单状态为暂停
            Order order = orderMapper.selectActiveByTableId(tableId);
            if (order != null) {
                order.setStatus(3); // 3表示暂停
                orderMapper.update(order);
            }
        }
    }

    @Override
    public void resumeTable(Long tableId) {
        // 获取当前操作员ID
        Long currentUserId = UserIdUtil.getUserId();
        if (currentUserId != null) {
            // 可以记录操作日志
            System.out.println("恢复球台操作员ID: " + currentUserId);
        }

        // 恢复逻辑：从暂停状态恢复
        Table table = tableMapper.selectById(tableId);
        if (table != null && table.getStatus() == 4) { // 4表示暂停
            // 恢复球台状态为使用中
            table.setStatus(1); // 使用中
            tableMapper.update(table);

            // 恢复订单状态为进行中
            Order order = orderMapper.selectActiveByTableId(tableId);
            if (order != null) {
                order.setStatus(0); // 0表示进行中
                orderMapper.update(order);
            }
        }
    }

    private void setTableFree(Long tableId) {
        Table table = tableMapper.selectById(tableId);
        if (table != null) {
            table.setStatus(0);
            table.setStartTime(null);
            table.setEndTime(null);
            table.setCurrentFee(BigDecimal.ZERO);
            tableMapper.update(table);
        }
    }

    private void setTableReserved(Long tableId, LocalDateTime startTime, LocalDateTime endTime) {
        Table table = tableMapper.selectById(tableId);
        if (table != null) {
            table.setStatus(2);
            table.setStartTime(startTime);
            table.setEndTime(endTime);
            tableMapper.update(table);
        }
    }

    private void setTableMaintenance(Long tableId) {
        Table table = tableMapper.selectById(tableId);
        if (table != null) {
            table.setStatus(3);
            tableMapper.update(table);
        }
    }




    private String generateOrderNumber() {
        return "ORD" + System.currentTimeMillis();
    }
}
